// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

import fs from "fs";
import path from "path";
import readline from "readline";

const header = `Copyright 2019-2023 Tauri Programme within The Commons Conservancy
SPDX-License-Identifier: Apache-2.0
SPDX-License-Identifier: MIT`;
const ignoredLicense = "// Copyright 2021 Jonas Kruckenberg";

const extensions = [".rs", ".js", ".ts", ".yml", ".swift", ".kt"];
const ignore = [
  "target",
  "templates",
  "node_modules",
  "gen",
  "dist",
  "dist-js",
  ".svelte-kit",
  "api-iife.js",
  "init-iife.js",
  ".build",
];

async function checkFile(file) {
  if (
    extensions.some((e) => file.endsWith(e)) &&
    !ignore.some((i) => file.endsWith(i))
  ) {
    const fileStream = fs.createReadStream(file);
    const rl = readline.createInterface({
      input: fileStream,
      crlfDelay: Infinity,
    });

    let contents = ``;
    let i = 0;
    for await (let line of rl) {
      // ignore empty lines, allow shebang, swift-tools-version and bundler license
      if (
        line.length === 0 ||
        line.startsWith("#!") ||
        line.startsWith("// swift-tools-version:") ||
        line === ignoredLicense
      ) {
        continue;
      }

      // strip comment marker
      if (line.startsWith("// ")) {
        line = line.substring(3);
      } else if (line.startsWith("# ")) {
        line = line.substring(2);
      }

      contents += line;
      if (++i === 3) {
        break;
      }
      contents += "\n";
    }
    if (contents !== header) {
      return true;
    }
  }
  return false;
}

async function check(src) {
  const missingHeader = [];

  for (const entry of fs.readdirSync(src, {
    withFileTypes: true,
  })) {
    const p = path.join(src, entry.name);

    if (entry.isSymbolicLink() || ignore.includes(entry.name)) {
      continue;
    }

    if (entry.isDirectory()) {
      const missing = await check(p);
      missingHeader.push(...missing);
    } else {
      const isMissing = await checkFile(p);
      if (isMissing) {
        missingHeader.push(p);
      }
    }
  }

  return missingHeader;
}

const [_bin, _script, ...files] = process.argv;

if (files.length > 0) {
  async function run() {
    const missing = [];
    for (const f of files) {
      const isMissing = await checkFile(f);
      if (isMissing) {
        missing.push(f);
      }
    }
    if (missing.length > 0) {
      console.log(missing.join("\n"));
      process.exit(1);
    }
  }

  run();
} else {
  check(path.resolve(new URL(import.meta.url).pathname, "../../..")).then(
    (missing) => {
      if (missing.length > 0) {
        console.log(missing.join("\n"));
        process.exit(1);
      }
    },
  );
}
